﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using PromoServer.Library.Data;
using PromoServer.Library.Entities;
using PromoServer.Library;
using System.IO;

namespace PromoServer_WPF.Views
{
    /// <summary>
    /// Interaction logic for DeviceView.xaml
    /// 
    /// NOTES:
    /// The displayNameTextBox_TextChanged event is unstable when writing the value to the db, try adding Save button instead.
    /// The only way the event functions correctly is when you write to the text box twice, it will retain the first change made.
    /// 
    /// Remove threading boolean variable in settings and identify button click event
    /// </summary>
    public partial class DeviceView : UserControl
    {
        private PSData psData;
        private Device currentDevice;
        private PromoSocketServer pServer;

        private bool statusDisplaySwitch = false;
        private string statusMessage = string.Empty;
        private int statusDisplaySeconds = 0;

        BackgroundWorker statusUpdateBackgroundWorker;
        BackgroundWorker identifyBackgroundWorker;
        BackgroundWorker displayDefaultBackgroundWorker;
        BackgroundWorker displayCustomBackgroundWorker;
        BackgroundWorker sendDefaultLayoutBackgroundWorker;
        BackgroundWorker sendCustomLayoutBackgroundWorker;

        #region CTR

        public DeviceView(Device device)
        {
            InitializeComponent();

            // Initialize background workers
            statusUpdateBackgroundWorker = new BackgroundWorker();
            statusUpdateBackgroundWorker.WorkerReportsProgress = true;
            statusUpdateBackgroundWorker.DoWork += new DoWorkEventHandler(statusUpdate_DoWork);
            statusUpdateBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(statusUpdate_ProgressChanged);
            statusUpdateBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(statusUpdate_RunWorkerCompleted);

            identifyBackgroundWorker = new BackgroundWorker();
            identifyBackgroundWorker.WorkerReportsProgress = true;
            identifyBackgroundWorker.DoWork += new DoWorkEventHandler(sendIdentify_DoWork);
            identifyBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(sendIdentify_ProgressChanged);
            identifyBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sendIdentify_RunWorkerCompleted);

            displayDefaultBackgroundWorker = new BackgroundWorker();
            displayDefaultBackgroundWorker.WorkerReportsProgress = true;
            displayDefaultBackgroundWorker.DoWork += new DoWorkEventHandler(displayDefault_DoWork);
            displayDefaultBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(displayDefault_ProgressChanged);
            displayDefaultBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(displayDefault_RunWorkerCompleted);

            displayCustomBackgroundWorker = new BackgroundWorker();
            displayCustomBackgroundWorker.WorkerReportsProgress = true;
            displayCustomBackgroundWorker.DoWork += new DoWorkEventHandler(displayCustom_DoWork);
            displayCustomBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(displayCustom_ProgressChanged);
            displayCustomBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(displayCustom_RunWorkerCompleted);

            sendDefaultLayoutBackgroundWorker = new BackgroundWorker();
            sendDefaultLayoutBackgroundWorker.WorkerReportsProgress = true;
            sendDefaultLayoutBackgroundWorker.DoWork += new DoWorkEventHandler(sendDefault_DoWork);
            sendDefaultLayoutBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(sendDefault_ProgressChanged);
            sendDefaultLayoutBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sendDefault_RunWorkerCompleted);

            sendCustomLayoutBackgroundWorker = new BackgroundWorker();
            sendCustomLayoutBackgroundWorker.WorkerReportsProgress = true;
            sendCustomLayoutBackgroundWorker.DoWork += new DoWorkEventHandler(sendCustom_DoWork);
            sendCustomLayoutBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(sendCustom_ProgressChanged);
            sendCustomLayoutBackgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(sendCustom_RunWorkerCompleted);

            // Initialize PS objects
            psData = new PSData();
            pServer = new PromoSocketServer();

            // Set the data context of the view
            currentDevice = device;
            this.DataContext = currentDevice;

            // Start status update process
            statusUpdateBackgroundWorker.RunWorkerAsync();
        }

        #endregion

        #region HELPER_FUNCTIONS

        private void updateStatusBar(string statusText, int displaySeconds)
        {
            // Set status values
            statusMessage = statusText;
            statusDisplaySeconds = displaySeconds;

            // Flip display switch to show status text
            statusDisplaySwitch = true;
        }

        private void resolutionChanged()
        {
            // Display message to user regarding new device resolution
            updateStatusBar("WARNING: The device resolution has changed and may not display correctly until a new layout is sent", 0);
        }

        private void disableInterface()
        {
            this.identifyButton.IsEnabled = false;
            this.displayCustomButton.IsEnabled = false;
            this.displayDefaultButton.IsEnabled = false;

            this.customLayoutButton.IsEnabled = false;
            this.defaultLayoutButton.IsEnabled = false;
            this.sendCustomLayoutButton.IsEnabled = false;
            this.sendDefaultLayoutButton.IsEnabled = false;
        }

        private void enableInterface()
        {
            this.identifyButton.IsEnabled = true;
            this.displayCustomButton.IsEnabled = true;
            this.displayDefaultButton.IsEnabled = true;

            this.customLayoutButton.IsEnabled = true;
            this.defaultLayoutButton.IsEnabled = true;
            this.sendCustomLayoutButton.IsEnabled = true;
            this.sendDefaultLayoutButton.IsEnabled = true;
        }

        private void removeDevice()
        {
            try
            {
                //// Delete the devices custom layout images
                //foreach (LayoutContent layout in currentDevice.GetCustomLayouts())
                //{
                //    deleteLayoutImage(layout.ContentFileName);
                //}

                //// Delete the devices default layout images
                //foreach (LayoutContent layout in currentDevice.GetDefaultLayouts())
                //{
                //    deleteLayoutImage(layout.ContentFileName);
                //}

                //// Delete device data from database
                //psData.DeleteDevice(currentDevice);

                //// Remove layout view from stack panel
                //StackPanel mainStackPanel = (StackPanel)this.Parent;
                //mainStackPanel.Children.Remove(this);
            }
            catch (Exception ex)
            {
                // Display error to user
                MessageBox.Show("Failed to remove device. Error: " + ex.Message);
            }
        }

        private void deleteLayoutImage(string imageFilePath)
        {
            try
            {
                if (File.Exists(imageFilePath))
                    File.Delete(imageFilePath);
            }
            catch (Exception ex)
            {
                // Display error to user
                MessageBox.Show("Failed to delete layout images. Error: " + ex.Message);
            }
        }

        private void displayCustom()
        {
            updateStatusBar("Attempting to find device...", 0);

            displayCustomBackgroundWorker.RunWorkerAsync();
        }

        private void displayDefault()
        {
            updateStatusBar("Attempting to find device...", 0);

            displayDefaultBackgroundWorker.RunWorkerAsync();
        }

        private void displayIdentify()
        {
            updateStatusBar("Attempting to find device...", 0);

            identifyBackgroundWorker.RunWorkerAsync();
        }

        #endregion

        #region BACKGROUND_WORKER_STATUS_UPDATE
        
        private void statusUpdate_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                if (statusDisplaySwitch)
                {
                    statusDisplaySwitch = false;
                    statusUpdateBackgroundWorker.ReportProgress(0, statusMessage);
                    if (statusDisplaySeconds != 0)
                    {
                        int displayMilSeconds = statusDisplaySeconds * 1000;
                        Thread.Sleep(displayMilSeconds);
                        statusUpdateBackgroundWorker.ReportProgress(100, "");
                    }
                }
                else
                    Thread.Sleep(50);
            }
        }

        private void statusUpdate_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            statusBarTextBlock.Text = (string)e.UserState;
        }

        private void statusUpdate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

        #endregion

        #region BACKGROUND_WORKER_IDENTIFY

        private void sendIdentify_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!pServer.IdentifyClient(currentDevice))
            {
                identifyBackgroundWorker.ReportProgress(0);
            }
            else
            {
                identifyBackgroundWorker.ReportProgress(100);
            }
        }

        private void sendIdentify_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
                updateStatusBar("Successfully found device. The devices monitor should now display the identification screen.", 0);
            else
                updateStatusBar("Failed to find device. Please make sure the device is powered on.", 0);
        }

        private void sendIdentify_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Work finished
        }

        #endregion

        #region BACKGROUND_WORKER_DISPLAY_DEFAULT

        private void displayDefault_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!pServer.DisplayDefaultLayout(currentDevice))
            {
                displayDefaultBackgroundWorker.ReportProgress(0);
            }
            else
            {
                displayDefaultBackgroundWorker.ReportProgress(100);
            }
        }

        private void displayDefault_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
                updateStatusBar("Successfully updated device. The devices monitor should now display the default screen layout.", 0);
            else
                updateStatusBar("Failed to update device. Please make sure the device is powered on.", 0);
        }

        private void displayDefault_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Work finished
        }

        #endregion

        #region BACKGROUND_WORKER_DISPLAY_CUSTOM

        private void displayCustom_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!pServer.DisplayCustomLayout(currentDevice))
            {
                displayCustomBackgroundWorker.ReportProgress(0);
            }
            else
            {
                displayCustomBackgroundWorker.ReportProgress(100);
            }
        }

        private void displayCustom_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
                updateStatusBar("Successfully updated device. The devices monitor should now display the custom screen layout.", 0);
            else
                updateStatusBar("Failed to update device. Please make sure the device is powered on.", 0);
        }

        private void displayCustom_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Work finished
        }

        #endregion

        #region BACKGROUND_WORKER_SEND_DEFAULT_LAYOUT

        private void sendDefault_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!pServer.SendDefaultContent(currentDevice))
                sendDefaultLayoutBackgroundWorker.ReportProgress(0);
            else
                sendDefaultLayoutBackgroundWorker.ReportProgress(100);
        }

        private void sendDefault_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
                updateStatusBar("Successfully sent default layout to device.", 0);
            else
                updateStatusBar("Failed to send default layout to device. Please make sure the device is powered on.", 0);
        }

        private void sendDefault_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (MessageBox.Show("The default layout has been sent. Do you want the device to display this now?", "Show layout now?", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                displayDefault();
            }

            enableInterface();
        }

        #endregion

        #region BACKGROUND_WORKER_SEND_CUSTOM_LAYOUT

        private void sendCustom_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!pServer.SendCustomContent(currentDevice))
                sendCustomLayoutBackgroundWorker.ReportProgress(0);
            else
                sendCustomLayoutBackgroundWorker.ReportProgress(100);
        }

        private void sendCustom_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 100)
                updateStatusBar("Successfully sent custom layout to device.", 0);
            else
                updateStatusBar("Failed to send custom layout to device. Please make sure the device is powered on.", 0);
        }

        private void sendCustom_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (MessageBox.Show("The custom layout has been sent. Do you want the device to display this now?", "Show layout now?", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                displayCustom();
            }

            enableInterface();
        }

        #endregion

        #region BUTTON_CLICK_EVENTS

        private void customLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Load list of layouts
                //List<LayoutContent> layouts = currentDevice.GetCustomLayouts();

                //DesignLayoutWindow designLayoutWindow = new DesignLayoutWindow(layouts, currentDevice.DeviceID, "custom");
                //designLayoutWindow.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void defaultLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Load list of layouts
                //List<LayoutContent> layouts = currentDevice.GetDefaultLayouts();

                //DesignLayoutWindow designLayoutWindow = new DesignLayoutWindow(layouts, currentDevice.DeviceID, "default");
                //designLayoutWindow.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void sendDefaultLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            disableInterface();

            updateStatusBar("Sending default layout...", 0);

            sendDefaultLayoutBackgroundWorker.RunWorkerAsync();
        }

        private void sendCustomLayoutButton_Click(object sender, RoutedEventArgs e)
        {
            disableInterface();

            updateStatusBar("Sending custom layout...", 0);

            sendCustomLayoutBackgroundWorker.RunWorkerAsync();
        }

        private void removeDeviceButton_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to remove this device? WARNING: This should only be done if the device no longer exists.", "Are you sure?", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
            {
                removeDevice();
            }
        }

        private void identifyButton_Click(object sender, RoutedEventArgs e)
        {
            displayIdentify();
        }

        private void displayDefaultButton_Click(object sender, RoutedEventArgs e)
        {
            displayDefault();
        }

        private void displayCustomButton_Click(object sender, RoutedEventArgs e)
        {
            displayCustom();
        }

        #endregion

    }
}
